<template>
  <div class="effect-group line opacity-wrap">
    <label
      :class="['opacity-label', { 'is-setting': getSettingFlag(EFFECTS_PROPERTY.Opacity) }]"
      @click="openSetting(EFFECTS_PROPERTY.Opacity, $event)"
    >
      <span>透明度</span>
    </label>
    <div>
      <slider-configurator
        :modelValue="state.opacity"
        :controls="false"
        :showUnit="true"
        @update:modelValue="updateOpacity"
      ></slider-configurator>
    </div>
  </div>
  <div class="effect-group line outline-wrap">
    <label
      :class="['outline-label', { 'is-setting': getSettingFlag(EFFECTS_PROPERTY.Outline) }]"
      @click="openSetting(EFFECTS_PROPERTY.Outline, $event)"
    >
      <span>轮廓</span>
    </label>
    <div class="outline-content">
      <tabs-group-configurator
        :options="outlineOptions"
        :modelValue="state.activedType"
        label-width="52"
        effect="light"
        placement="top"
        @update:modelValue="selectOutlineStyle"
      ></tabs-group-configurator>
    </div>
    <div v-if="state.activedType && state.activedType !== 'none'" class="outline-setting">
      <div class="outline-row-wrap">
        <div class="left outline-width">
          <label class="outline-label"><span>宽度</span></label>
          <input-select
            :modelValue="state.outlineWidth"
            :suffixValue="state.outlineWidthSuffix"
            :options="outlineSuffixOptions"
            @input-change="outlineWidthChange"
            @select-change="outlineWidthSuffixChange"
          ></input-select>
        </div>
        <div class="right outline-width">
          <label class="outline-label"><span>偏移</span></label>
          <input-select
            :modelValue="state.outlineOffset"
            :suffixValue="state.outlineOffsetSuffix"
            :options="outlineSuffixOptions"
            @input-change="outlineOffsetChange"
            @select-change="outlineOffsetSuffixChange"
          ></input-select>
        </div>
      </div>

      <div class="outline-color">
        <label class="outline-label"><span>颜色</span></label>
        <color-configurator :modelValue="state.outlineColor" @change="changeOutlineColor" />
      </div>
    </div>
  </div>
  <div class="effect-group line cursor-wrap">
    <label
      :class="['cursor-label', { 'is-setting': getSettingFlag(EFFECTS_PROPERTY.Cursor) }]"
      @click="openSetting(EFFECTS_PROPERTY.Cursor, $event)"
    >
      <span>光标</span>
    </label>
    <div>
      <tiny-select v-model="state.cursorValue" placeholder="请选择" @change="cursorChange">
        <tiny-option-group
          v-for="group in cursorGroup"
          :key="group.label"
          :label="group.label"
          :disabled="group.disabled"
        >
          <tiny-option v-for="item in group.options" :key="item.value" :label="item.label" :value="item.value">
            <div class="cursor-option">
              <span class="item-icon"><svg-icon :name="item.icon"></svg-icon></span>
              <span class="item-label">{{ item.label }}</span>
            </div>
          </tiny-option>
        </tiny-option-group>
      </tiny-select>
    </div>
  </div>
  <modal-mask v-if="state.showModal" @close="state.showModal = false">
    <reset-button @reset="reset" />
  </modal-mask>
</template>

<script>
/* metaService: engine.setting.styles.EffectGroup */
import { reactive } from 'vue'
import { Select, Option, OptionGroup } from '@opentiny/vue'
import { ColorConfigurator, SliderConfigurator, TabsGroupConfigurator } from '@opentiny/tiny-engine-configurator'
import ModalMask, { useModal } from '../inputs/ModalMask.vue'
import ResetButton from '../inputs/ResetButton.vue'
import InputSelect from '../inputs/InputSelect.vue'
import { useProperties } from '../../js/useStyle'
import { EFFECTS_PROPERTY } from '../../js/styleProperty'
import { BORDER_STYLE_TYPE } from '../../js/cssType'

export default {
  components: {
    TinySelect: Select,
    TinyOption: Option,
    TinyOptionGroup: OptionGroup,
    SliderConfigurator,
    ColorConfigurator,
    TabsGroupConfigurator,
    ModalMask,
    ResetButton,
    InputSelect
  },
  props: {
    style: {
      type: Object,
      default: () => ({})
    }
  },
  emits: ['update'],
  setup(props, { emit }) {
    let activedName = []

    const cursorGroup = [
      {
        label: 'General',
        options: [
          {
            value: 'auto',
            label: 'auto',
            icon: 'cursor-auto'
          },
          {
            value: 'default',
            label: 'default',
            icon: 'cursor-auto'
          },
          {
            value: 'none',
            label: 'none',
            icon: 'cursor-none'
          }
        ]
      },
      {
        label: 'Links & Status',
        options: [
          {
            value: 'pointer',
            label: 'pointer',
            icon: 'cursor-pointer'
          },
          {
            value: 'not-allowed',
            label: 'not-allowed',
            icon: 'cursor-not-allowed'
          },
          {
            value: 'wait',
            label: 'wait',
            icon: 'cursor-wait'
          },
          {
            value: 'progress',
            label: 'progress',
            icon: 'cursor-progress'
          },
          {
            value: 'help',
            label: 'help',
            icon: 'cursor-help'
          },
          {
            value: 'context-menu',
            label: 'context-menu',
            icon: 'cursor-context-menu'
          }
        ]
      },
      {
        label: 'Selection',
        options: [
          {
            value: 'cell',
            label: 'cell',
            icon: 'cursor-cell'
          },
          {
            value: 'crosshair',
            label: 'crosshair',
            icon: 'cursor-crosshair'
          },
          {
            value: 'text',
            label: 'text',
            icon: 'cursor-text'
          },
          {
            value: 'vertical-text',
            label: 'vertical-text',
            icon: 'cursor-vertical-text'
          }
        ]
      },
      {
        label: 'Drag & Drop',
        options: [
          {
            value: 'grab',
            label: 'grab',
            icon: 'cursor-grab'
          },
          {
            value: 'grabbing',
            label: 'grabbing',
            icon: 'cursor-grabbing'
          },
          {
            value: 'alias',
            label: 'alias',
            icon: 'cursor-alias'
          },
          {
            value: 'copy',
            label: 'copy',
            icon: 'cursor-copy'
          },
          {
            value: 'move',
            label: 'move',
            icon: 'cursor-move'
          }
        ]
      },
      {
        label: 'Zoom',
        options: [
          {
            value: 'zoom-in',
            label: 'zoom-in',
            icon: 'cursor-zoom-in'
          },
          {
            value: 'zoom-out',
            label: 'zoom-out',
            icon: 'cursor-zoom-out'
          }
        ]
      },
      {
        label: 'Resize',
        options: [
          {
            value: 'col-resize',
            label: 'col-resize',
            icon: 'cursor-col-resize'
          },
          {
            value: 'row-resize',
            label: 'row-resize',
            icon: 'cursor-row-resize'
          },
          {
            value: 'nesw-resize',
            label: 'nesw-resize',
            icon: 'cursor-nesw-resize'
          },
          {
            value: 'nwse-resize',
            label: 'nwse-resize',
            icon: 'cursor-nwse-resize'
          },
          {
            value: 'ew-resize',
            label: 'ew-resize',
            icon: 'cursor-ew-resize'
          },
          {
            value: 'ns-resize',
            label: 'ns-resize',
            icon: 'cursor-ns-resize'
          },
          {
            value: 'n-resize',
            label: 'n-resize',
            icon: 'cursor-n-resize'
          },
          {
            value: 'w-resize',
            label: 'w-resize',
            icon: 'cursor-w-resize'
          },
          {
            value: 's-resize',
            label: 's-resize',
            icon: 'cursor-s-resize'
          },
          {
            value: 'e-resize',
            label: 'e-resize',
            icon: 'cursor-e-resize'
          },
          {
            value: 'nw-resize',
            label: 'nw-resize',
            icon: 'cursor-nw-resize'
          },
          {
            value: 'ne-resize',
            label: 'ne-resize',
            icon: 'cursor-ne-resize'
          },
          {
            value: 'sw-resize',
            label: 'sw-resize',
            icon: 'cursor-sw-resize'
          },
          {
            value: 'se-resize',
            label: 'se-resize',
            icon: 'cursor-se-resize'
          }
        ]
      }
    ]

    const outlineOptions = [
      {
        icon: 'cross',
        value: BORDER_STYLE_TYPE.None,
        content: 'none-无'
      },
      {
        icon: 'border-style-solid',
        value: BORDER_STYLE_TYPE.Solid,
        content: 'solid-实线'
      },
      {
        icon: 'border-style-dashed',
        value: BORDER_STYLE_TYPE.Dashed,
        content: 'dashed-虚线'
      },
      {
        icon: 'border-style-dotted',
        value: BORDER_STYLE_TYPE.Dotted,
        content: 'dotted-圆点'
      }
    ]

    const outlineSuffixOptions = [
      {
        label: 'PX',
        value: 'px'
      },
      {
        label: 'EM',
        value: 'em'
      },
      {
        label: 'REM',
        value: 'rem'
      },
      {
        label: 'CH',
        value: 'ch'
      },
      {
        label: 'VW',
        value: 'vw'
      },
      {
        label: 'VH',
        value: 'vh'
      }
    ]

    const state = reactive({
      opacity: 100,
      cursorValue: 'auto',
      activedType: null,
      outlineWidth: 3,
      outlineWidthSuffix: 'px',
      outlineOffset: 0,
      outlineOffsetSuffix: 'px',
      outlineColor: '#333333',
      showModal: false
    })

    const { setPosition } = useModal()

    const { getSettingFlag, getProperty } = useProperties({
      names: Object.values(EFFECTS_PROPERTY),
      parseNumber: true
    })

    const updateStyle = (properties) => {
      emit('update', properties)
    }

    const updateOpacity = (value) => {
      state.opacity = value
      updateStyle({
        [EFFECTS_PROPERTY.Opacity]: `${value / 100}`
      })
    }

    const cursorChange = (value) => {
      updateStyle({
        [EFFECTS_PROPERTY.Cursor]: value
      })
    }

    const openSetting = (name, event) => {
      if (getSettingFlag(name)) {
        if (name === 'outline') {
          activedName = [EFFECTS_PROPERTY.Outline, EFFECTS_PROPERTY.OutlineOffset]
        } else {
          activedName = [name]
        }
        setPosition(event)
        state.showModal = true
      }
    }

    const setOutlineStyle = () => {
      updateStyle({
        [EFFECTS_PROPERTY.Outline]: `${state.outlineWidth + state.outlineWidthSuffix} ${state.activedType} ${
          state.outlineColor
        }`
      })
    }

    const setOutlineOffset = () => {
      updateStyle({
        [EFFECTS_PROPERTY.OutlineOffset]: `${state.outlineOffset + state.outlineOffsetSuffix}`
      })
    }

    const selectOutlineStyle = (type) => {
      state.activedType = type

      if (type === 'none') {
        updateStyle({ [EFFECTS_PROPERTY.Outline]: null, [EFFECTS_PROPERTY.OutlineOffset]: null })
      } else {
        setOutlineStyle()
        setOutlineOffset()
      }
    }

    const outlineWidthChange = (val) => {
      state.outlineWidth = val
      setOutlineStyle()
    }

    const outlineWidthSuffixChange = (val) => {
      state.outlineWidthSuffix = val
      setOutlineStyle()
    }

    const outlineOffsetChange = (val) => {
      state.outlineOffset = val
      setOutlineOffset()
    }

    const outlineOffsetSuffixChange = (val) => {
      state.outlineOffsetSuffix = val
      setOutlineOffset()
    }

    const changeOutlineColor = (val) => {
      state.outlineColor = val?.target?.value || val || ''
      setOutlineStyle()
    }

    const reset = () => {
      activedName?.forEach((name) => {
        updateStyle({ [name]: null })
      })
      state.cursorValue = 'auto'
      state.activedType = null
      state.outlineWidth = 3
      state.outlineOffset = 0
      state.outlineColor = '#333333'
      state.outlineWidthSuffix = 'px'
      state.outlineOffsetSuffix = 'px'
      state.showModal = false
    }

    return {
      state,
      cursorGroup,
      outlineOptions,
      EFFECTS_PROPERTY,
      BORDER_STYLE_TYPE,
      outlineSuffixOptions,
      updateOpacity,
      getSettingFlag,
      openSetting,
      reset,
      cursorChange,
      selectOutlineStyle,
      outlineWidthChange,
      outlineWidthSuffixChange,
      outlineOffsetChange,
      outlineOffsetSuffixChange,
      changeOutlineColor,
      getProperty
    }
  }
}
</script>

<style lang="less" scoped>
.effect-group {
  display: grid;
  gap: 8px;
  grid-template-columns: 36px auto;
  align-items: center;
  margin-bottom: var(--te-common-vertical-item-spacing-normal);
  span {
    padding: 2px;
  }
  &:last-child {
    margin-bottom: 0;
  }
  .opacity-label,
  .outline-label,
  .cursor-label {
    color: var(--te-styles-common-text-color-secondary);
  }

  .is-setting {
    span {
      cursor: pointer;
      border-radius: 2px;
      color: var(--te-styles-common-setting-text-color);
      background-color: var(--te-styles-common-setting-bg-color);
    }
  }

  :deep(.slider-container) {
    .mate-numeric-input .mate-numeric-unit .tiny-select .tiny-input .tiny-input__inner {
      background-color: transparent;
    }
  }

  .outline-content {
    display: flex;
    color: var(--te-styles-common-text-color-secondary);
    .outline-content-svg {
      flex: 1;
      padding: 4px;
      font-size: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
      &:hover,
      &.selected {
        svg {
          color: var(--te-styles-effect-group-icon-color-active);
        }
      }
    }
  }
  .outline-setting {
    grid-column: 1 / -1;

    .outline-row-wrap {
      display: grid;
      gap: 4px 20px;
      grid-template-columns: 15px 1fr;
      align-items: center;
      margin-bottom: var(--te-common-vertical-item-spacing-normal);
      grid-template-columns: 45% auto;
      .left {
        display: grid;
        align-items: center;
        gap: 4px 20px;
        grid-template-columns: 23px 1fr;
      }
      .right {
        display: grid;
        align-items: center;
        gap: 4px 8px;
        grid-template-columns: 40px 1fr;
      }
    }

    .outline-color {
      display: grid;
      grid-template-columns: 36px auto;
      gap: 8px;
      align-items: center;
      margin-top: 8px;
    }
    .outline-label {
      margin-right: -16px;
      line-height: 16px;
      color: var(--te-styles-common-text-color-secondary);
      span {
        padding: 2px;
      }
    }
  }
}

.opacity-wrap {
  grid-template-columns: 40px auto;
}
</style>
